home *** CD-ROM | disk | FTP | other *** search
- /* copypix.c */
-
- /*
- * Mesa 3-D graphics library
- * Version: 1.2
- * Copyright (C) 1995 Brian Paul (brianp@ssec.wisc.edu)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
- /*
- $Id: copypix.c,v 1.17 1995/11/03 17:40:29 brianp Exp $
-
- $Log: copypix.c,v $
- * Revision 1.17 1995/11/03 17:40:29 brianp
- * fixed a varname typo, removed unused variables
- *
- * Revision 1.16 1995/10/19 15:47:12 brianp
- * added gamma support
- *
- * Revision 1.15 1995/10/16 15:25:49 brianp
- * added zooming for stencil drawing/copying
- *
- * Revision 1.14 1995/10/14 16:28:21 brianp
- * added glPixelZoom support
- *
- * Revision 1.13 1995/09/15 18:43:25 brianp
- * broke gl_copypixels into sub-functions
- * directly access DD.write_color_span under the right conditions
- *
- * Revision 1.12 1995/09/07 14:15:52 brianp
- * use CC.NewState convention
- * use DEFARRAY macro for MacIntosh support
- *
- * Revision 1.11 1995/08/04 13:07:28 brianp
- * changed some types involved in scale and bias operation
- *
- * Revision 1.10 1995/07/24 19:00:17 brianp
- * convert real window coords to ints with rounding, not truncating
- * changed calls to CLAMP() to prevent type warnings on Suns
- *
- * Revision 1.9 1995/06/12 15:52:07 brianp
- * renamed from copypixels.c to copypix.c
- *
- * Revision 1.8 1995/06/12 15:38:01 brianp
- * changed color arrays to GLubyte
- * added feedback and selection support
- *
- * Revision 1.7 1995/05/31 14:58:45 brianp
- * check for valid rasterpos, use gl_read_color|index_span()
- *
- * Revision 1.6 1995/05/22 21:02:41 brianp
- * Release 1.2
- *
- * Revision 1.5 1995/05/12 19:24:13 brianp
- * replaced CC.Mode!=0 with INSIDE_BEGIN_END
- *
- * Revision 1.4 1995/04/18 15:47:59 brianp
- * added a cast to prevent warning on Suns
- *
- * Revision 1.3 1995/03/13 20:54:53 brianp
- * added read buffer logic
- *
- * Revision 1.2 1995/03/04 19:29:44 brianp
- * 1.1 beta revision
- *
- * Revision 1.1 1995/02/24 14:20:20 brianp
- * Initial revision
- *
- */
-
-
- #include <string.h>
- #include "context.h"
- #include "dd.h"
- #include "depth.h"
- #include "feedback.h"
- #include "gamma.h"
- #include "list.h"
- #include "macros.h"
- #include "pixel.h"
- #include "span.h"
- #include "stencil.h"
-
-
- #ifndef NULL
- # define NULL 0
- #endif
-
-
-
-
- static void copy_rgb_pixels( GLint srcx, GLint srcy, GLint width, GLint height,
- GLint destx, GLint desty )
- {
- DEFARRAY( GLint, idepth, MAX_WIDTH );
- DEFARRAY( GLubyte, red, MAX_WIDTH );
- DEFARRAY( GLubyte, green, MAX_WIDTH );
- DEFARRAY( GLubyte, blue, MAX_WIDTH );
- DEFARRAY( GLubyte, alpha, MAX_WIDTH );
- GLboolean scale_or_bias, quick_draw, zoom;
- GLint sy, dy, stepy;
- GLint i, j;
- GLboolean setbuffer;
- GLuint gamma_bit;
-
- if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
- zoom = GL_FALSE;
- }
- else {
- zoom = GL_TRUE;
- }
-
- /* Determine if copy should be done bottom-to-top or top-to-bottom */
- if (srcy<desty) {
- /* top-down max-to-min */
- sy = srcy + height - 1;
- dy = desty + height - 1;
- stepy = -1;
- }
- else {
- /* bottom-up min-to-max */
- sy = srcy;
- dy = desty;
- stepy = 1;
- }
-
- scale_or_bias = CC.Pixel.RedScale!=1.0 || CC.Pixel.RedBias!=0.0
- || CC.Pixel.GreenScale!=1.0 || CC.Pixel.GreenBias!=0.0
- || CC.Pixel.BlueScale!=1.0 || CC.Pixel.BlueBias!=0.0
- || CC.Pixel.AlphaScale!=1.0 || CC.Pixel.AlphaBias!=0.0;
-
- if (CC.Depth.Test) {
- /* fill in array of z values */
- GLint z = (GLint) (CC.Current.RasterPos[2] * MAX_DEPTH);
- for (i=0;i<width;i++) {
- idepth[i] = z;
- }
- }
-
- /* temporarily disable gamma correction */
- gamma_bit = CC.RasterMask & GAMMA_BIT;
- CC.RasterMask &= ~GAMMA_BIT;
-
- if (CC.RasterMask==0 && destx>=0 && destx+width<=CC.BufferWidth && !zoom) {
- quick_draw = GL_TRUE;
- }
- else {
- quick_draw = GL_FALSE;
- }
-
- /* If read and draw buffer are different we must do buffer switching */
- setbuffer = CC.Pixel.ReadBuffer!=CC.Color.DrawBuffer;
-
- for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
- /* read */
-
- if (setbuffer) {
- (*DD.set_buffer)( CC.Pixel.ReadBuffer );
- }
- gl_read_color_span( width, srcx, sy, red, green, blue, alpha );
-
- if (scale_or_bias) {
- GLfloat rbias = CC.Pixel.RedBias * CC.RedScale;
- GLfloat gbias = CC.Pixel.GreenBias * CC.GreenScale;
- GLfloat bbias = CC.Pixel.BlueBias * CC.BlueScale;
- GLfloat abias = CC.Pixel.AlphaBias * CC.AlphaScale;
- GLint rmax = (GLint) CC.RedScale;
- GLint gmax = (GLint) CC.GreenScale;
- GLint bmax = (GLint) CC.BlueScale;
- GLint amax = (GLint) CC.AlphaScale;
- for (i=0;i<width;i++) {
- GLint r = red[i] * CC.Pixel.RedScale + rbias;
- GLint g = green[i] * CC.Pixel.GreenScale + gbias;
- GLint b = blue[i] * CC.Pixel.BlueScale + bbias;
- GLint a = alpha[i] * CC.Pixel.AlphaScale + abias;
- red[i] = CLAMP( r, 0, rmax );
- green[i] = CLAMP( g, 0, gmax );
- blue[i] = CLAMP( b, 0, bmax );
- alpha[i] = CLAMP( a, 0, amax );
- }
- }
-
- if (CC.Pixel.MapColorFlag) {
- GLfloat r = (CC.Pixel.MapRtoRsize-1) / CC.RedScale;
- GLfloat g = (CC.Pixel.MapGtoGsize-1) / CC.GreenScale;
- GLfloat b = (CC.Pixel.MapBtoBsize-1) / CC.BlueScale;
- GLfloat a = (CC.Pixel.MapAtoAsize-1) / CC.AlphaScale;
- for (i=0;i<width;i++) {
- GLint ir = red[i] * r;
- GLint ig = green[i] * g;
- GLint ib = blue[i] * b;
- GLint ia = alpha[i] * a;
- red[i] = (GLint) (CC.Pixel.MapRtoR[ir] * CC.RedScale);
- green[i] = (GLint) (CC.Pixel.MapGtoG[ig] * CC.GreenScale);
- blue[i] = (GLint) (CC.Pixel.MapBtoB[ib] * CC.BlueScale);
- alpha[i] = (GLint) (CC.Pixel.MapAtoA[ia] * CC.AlphaScale);
- }
- }
-
- /* write */
- if (setbuffer) {
- (*DD.set_buffer)( CC.Color.DrawBuffer );
- }
- if (quick_draw && dy>=0 && dy<CC.BufferHeight) {
- (*DD.write_color_span)( width, destx, dy,
- red, green, blue, alpha, NULL);
- }
- else if (zoom) {
- gl_write_zoomed_color_span( width, destx, dy, idepth,
- red, green, blue, alpha, desty );
- }
- else {
- gl_write_color_span( width, destx, dy, idepth,
- red, green, blue, alpha, GL_BITMAP );
- }
- }
- UNDEFARRAY( idepth );
- UNDEFARRAY( red );
- UNDEFARRAY( green );
- UNDEFARRAY( blue );
- UNDEFARRAY( alpha );
-
- /* re-enable gamma correction */
- CC.RasterMask |= gamma_bit;
- }
-
-
-
- static void copy_ci_pixels( GLint srcx, GLint srcy, GLint width, GLint height,
- GLint destx, GLint desty )
- {
- GLint idepth[MAX_WIDTH];
- GLuint indx[MAX_WIDTH];
- GLint sy, dy, stepy;
- GLint i, j;
- GLboolean setbuffer, zoom;
-
- if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
- zoom = GL_FALSE;
- }
- else {
- zoom = GL_TRUE;
- }
-
- /* Determine if copy should be bottom-to-top or top-to-bottom */
- if (srcy<desty) {
- /* top-down max-to-min */
- sy = srcy + height - 1;
- dy = desty + height - 1;
- stepy = -1;
- }
- else {
- /* bottom-up min-to-max */
- sy = srcy;
- dy = desty;
- stepy = 1;
- }
-
- if (CC.Depth.Test) {
- /* fill in array of z values */
- GLint z = (GLint) (CC.Current.RasterPos[2] * MAX_DEPTH);
- for (i=0;i<width;i++) {
- idepth[i] = z;
- }
- }
-
- /* If read and draw buffer are different we must do buffer switching */
- setbuffer = CC.Pixel.ReadBuffer!=CC.Color.DrawBuffer;
-
- for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
- /* read */
- if (setbuffer) {
- (*DD.set_buffer)( CC.Pixel.ReadBuffer );
- }
- gl_read_index_span( width, srcx, sy, indx );
-
- /* shift, offset */
- if (CC.Pixel.IndexShift || CC.Pixel.IndexOffset) {
- if (CC.Pixel.IndexShift<0) {
- for (i=0;i<width;i++) {
- indx[i] = (indx[i] >> -CC.Pixel.IndexShift)
- + CC.Pixel.IndexOffset;
- }
- }
- else {
- for (i=0;i<width;i++) {
- indx[i] = (indx[i] << CC.Pixel.IndexShift)
- + CC.Pixel.IndexOffset;
- }
- }
- }
-
- /* mapping */
- if (CC.Pixel.MapColorFlag) {
- for (i=0;i<width;i++) {
- if (indx[i] < CC.Pixel.MapItoIsize) {
- indx[i] = CC.Pixel.MapItoI[ indx[i] ];
- }
- }
- }
-
- /* write */
- if (setbuffer) {
- (*DD.set_buffer)( CC.Color.DrawBuffer );
- }
- if (zoom) {
- gl_write_zoomed_index_span( width, destx, dy, idepth, indx, desty );
- }
- else {
- gl_write_index_span( width, destx, dy, idepth, indx, GL_BITMAP );
- }
- }
- }
-
-
-
- static void copy_depth_pixels( GLint srcx, GLint srcy,
- GLint width, GLint height,
- GLint destx, GLint desty )
- {
- GLfloat depth[MAX_WIDTH];
- GLint idepth[MAX_WIDTH];
- GLuint indx[MAX_WIDTH];
- GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
- GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
- GLint sy, dy, stepy;
- GLint i, j;
- GLboolean zoom;
-
- if (!CC.DepthBuffer) {
- gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
- return;
- }
-
- if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
- zoom = GL_FALSE;
- }
- else {
- zoom = GL_TRUE;
- }
-
- /* Determine if copy should be bottom-to-top or top-to-bottom */
- if (srcy<desty) {
- /* top-down max-to-min */
- sy = srcy + height - 1;
- dy = desty + height - 1;
- stepy = -1;
- }
- else {
- /* bottom-up min-to-max */
- sy = srcy;
- dy = desty;
- stepy = 1;
- }
-
- /* setup colors or indexes */
- if (CC.RGBAflag) {
- GLubyte r, g, b, a;
- r = (GLint) (CC.Current.Color[0] * CC.RedScale);
- g = (GLint) (CC.Current.Color[1] * CC.GreenScale);
- b = (GLint) (CC.Current.Color[2] * CC.BlueScale);
- a = (GLint) (CC.Current.Color[3] * CC.AlphaScale);
- if (CC.RasterMask & GAMMA_BIT) {
- gl_apply_gamma( 1, &r, &g, &b );
- }
- MEMSET( red, (int) r, width );
- MEMSET( green, (int) g, width );
- MEMSET( blue, (int) b, width );
- MEMSET( alpha, (int) a, width );
- }
- else {
- for (i=0;i<width;i++) {
- indx[i] = CC.Current.Index;
- }
- }
-
- for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
- /* read */
- gl_read_depth_span( width, srcx, sy, depth );
- /* scale, bias, clamp */
- for (i=0;i<width;i++) {
- GLfloat d = depth[i] * CC.Pixel.DepthScale + CC.Pixel.DepthBias;
- idepth[i] = (GLint) (CLAMP( d, 0.0, 1.0 ) * MAX_DEPTH);
- }
- /* write */
- if (CC.RGBAflag) {
- if (zoom) {
- gl_write_zoomed_color_span( width, destx, dy, idepth,
- red, green, blue, alpha, desty );
- }
- else {
- gl_write_color_span( width, destx, dy, idepth,
- red, green, blue, alpha, GL_BITMAP );
- }
- }
- else {
- if (zoom) {
- gl_write_zoomed_index_span( width, destx, dy, idepth, indx, desty);
- }
- else {
- gl_write_index_span( width, destx, dy, idepth, indx, GL_BITMAP );
- }
- }
- }
- }
-
-
-
- static void copy_stencil_pixels( GLint srcx, GLint srcy,
- GLint width, GLint height,
- GLint destx, GLint desty )
- {
- GLubyte stencil[MAX_WIDTH];
- GLint sy, dy, stepy;
- GLint i, j;
- GLboolean zoom;
-
- if (!CC.StencilBuffer) {
- gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
- return;
- }
-
- if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
- zoom = GL_FALSE;
- }
- else {
- zoom = GL_TRUE;
- }
-
- /* Determine if copy should be bottom-to-top or top-to-bottom */
- if (srcy<desty) {
- /* top-down max-to-min */
- sy = srcy + height - 1;
- dy = desty + height - 1;
- stepy = -1;
- }
- else {
- /* bottom-up min-to-max */
- sy = srcy;
- dy = desty;
- stepy = 1;
- }
-
- for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
- /* read */
- gl_read_stencil_span( width, srcx, sy, stencil );
- /* shift, offset */
- if (CC.Pixel.IndexShift<0) {
- for (i=0;i<width;i++) {
- stencil[i] = (stencil[i] >> -CC.Pixel.IndexShift)
- + CC.Pixel.IndexOffset;
- }
- }
- else {
- for (i=0;i<width;i++) {
- stencil[i] = (stencil[i] << CC.Pixel.IndexShift)
- + CC.Pixel.IndexOffset;
- }
- }
- /* mapping */
- if (CC.Pixel.MapStencilFlag) {
- for (i=0;i<width;i++) {
- if ((GLint) stencil[i] < CC.Pixel.MapStoSsize) {
- stencil[i] = CC.Pixel.MapStoS[ stencil[i] ];
- }
- }
- }
- /* write */
- if (zoom) {
- gl_write_zoomed_stencil_span( width, destx, dy, stencil, desty );
- }
- else {
- gl_write_stencil_span( width, destx, dy, stencil );
- }
- }
- }
-
-
-
-
- void gl_copypixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
- GLenum type )
- {
- GLint destx, desty;
-
- if (INSIDE_BEGIN_END) {
- gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
- return;
- }
-
- if (width<0 || height<0) {
- gl_error( GL_INVALID_VALUE, "glCopyPixels" );
- return;
- }
-
- if (CC.NewState) {
- gl_update_state();
- }
-
- if (CC.RenderMode==GL_RENDER) {
- /* Destination of copy: */
- if (!CC.Current.RasterPosValid) {
- return;
- }
- destx = (GLint) (CC.Current.RasterPos[0] + 0.5F);
- desty = (GLint) (CC.Current.RasterPos[1] + 0.5F);
-
- if (type==GL_COLOR && CC.RGBAflag) {
- copy_rgb_pixels( srcx, srcy, width, height, destx, desty );
- }
- else if (type==GL_COLOR && !CC.RGBAflag) {
- copy_ci_pixels( srcx, srcy, width, height, destx, desty );
- }
- else if (type==GL_DEPTH) {
- copy_depth_pixels( srcx, srcy, width, height, destx, desty );
- }
- else if (type==GL_STENCIL) {
- copy_stencil_pixels( srcx, srcy, width, height, destx, desty );
- }
- else {
- gl_error( GL_INVALID_ENUM, "glCopyPixels" );
- }
- }
- else if (CC.RenderMode==GL_FEEDBACK) {
- APPEND_TOKEN( (GLfloat) GL_COPY_PIXEL_TOKEN );
- gl_feedback_vertex( CC.Current.RasterPos[0],
- CC.Current.RasterPos[1],
- CC.Current.RasterPos[2],
- CC.Current.RasterPos[3],
- CC.Current.Color, CC.Current.Index,
- CC.Current.TexCoord );
- }
- else if (CC.RenderMode==GL_SELECT) {
- /* TODO: verify that this is correct */
- CC.HitFlag = GL_TRUE;
- if (CC.Current.RasterPos[2] < CC.HitMinZ) {
- CC.HitMinZ = CC.Current.RasterPos[2];
- }
- if (CC.Current.RasterPos[2] > CC.HitMaxZ) {
- CC.HitMaxZ = CC.Current.RasterPos[2];
- }
- }
-
- }
-
-
-
- void glCopyPixels( GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum type )
- {
- if (CC.CompileFlag) {
- gl_save_copypixels( x, y, width, height, type );
- }
- if (CC.ExecuteFlag) {
- gl_copypixels( x, y, width, height, type );
- }
- }
-
-
-